# -*- coding: utf-8 -*-
import OpenSSL

OpenSSL.SSL.SSLv3_METHOD = OpenSSL.SSL.TLSv1_METHOD
from apnsclient import Session, APNs, Message
import logging

try:
    import setting
except ImportError:
    import sys

    sys.path.append('..')
    import setting
from core.cache import redis

logger = logging.getLogger('push')

session_dev = Session()
session_dev.new_connection("push_sandbox", cert_file="./development.pem", passphrase='mbmb')
session_pro = Session()
session_pro.new_connection("push_production", cert_file="./production.pem", passphrase='mbmb')
session_enter_pro = Session()
session_enter_pro.new_connection("push_production", cert_file="./enterprise_production.pem", passphrase='mbmb')
session_micheng_pro = Session()
session_micheng_pro.new_connection("push_production", cert_file="./MiCheng_production.pem", passphrase='mbmb')
session_kele_dev = Session()
session_kele_dev.new_connection("push_sandbox", cert_file="./kele_development.pem", passphrase='1234')
session_kele_pro = Session()
session_kele_pro.new_connection("push_production", cert_file="./kele_production.pem", passphrase='1234')

ALERT = {
    'newmessage': u'家庭圈新消息',
    'newfamily': u'用户请求加入家庭圈',
    'hasaddbaby': u'家庭圈添加新宝贝',
    # 'nowlocate'        :u'宝贝最新位置',
    'safemessage': u'进入离开安全区域',
    'babyinfomodify': u'宝贝信息已变更',
    'babyhasdelete': u'宝贝从家庭圈被删除',
    # 'userhasdelete'    :u'用户从家庭圈被删除',
    # 'babyauthok'       :u'腕表确认添加',
    # 'babyauthno'       :u'腕表拒绝添加',
    'lowvoltage': u'腕表低电量',
    'babysos': u'宝贝sos',
    # 'babystatus'       :u'腕表在线状态改变'
}


def push_apns(tokenlist, data):
    if data['type'] in ('babystatus', 'nowlocate', 'babyauthok', 'babyauthno', 'userhasdelete'):
        return None
    if data['type'] == 'custom':
        alert = data['content']
        data = {'type': 'custom'}
    else:
        alert = ALERT[data['type']]

    for tokens, version in tokenlist:
        logger.info(repr(data))
        message = Message(tokens, alert=alert, sound='default', data=data)

        if not version or version == 'official_develop':
            k = 1
            while k <= 5:
                if redis.sismember('official_develop_fail', tokens):
                    break
                con = session_dev.get_connection("push_sandbox", cert_file="./development.pem", passphrase='mbmb')
                srv = APNs(con)
                try:
                    res = srv.send(message)
                except OpenSSL.SSL.WantReadError:
                    logger.error('want read error')
                except:
                    logger.error('Dev fail:', exc_info=True)
                else:
                    for token, reason in res.failed.items():
                        code, errmsg = reason
                        logger.error("Dev Device failed: {0}, reason: {1}".format(token, errmsg))
                        redis.sadd('official_develop_fail', token)
                    for code, errmsg in res.errors:
                        logger.error("Dev Error: {}".format(errmsg))
                    if res.needs_retry():
                        logger.error('Dev need retry')
                        message = res.retry()
                    else:
                        break
                k += 1

        if not version or version == 'official_produce':
            k = 1
            while k <= 5:
                if redis.sismember('official_produce_fail', tokens):
                    break
                con = session_pro.get_connection("push_production", cert_file="./production.pem", passphrase='mbmb')
                srv = APNs(con)
                try:
                    res = srv.send(message)
                except OpenSSL.SSL.WantReadError:
                    logger.error('want read error')
                except:
                    logger.error('Pro fail:', exc_info=True)
                else:
                    for token, reason in res.failed.items():
                        code, errmsg = reason
                        logger.error("Pro Device failed: {0}, reason: {1}".format(token, errmsg))
                        redis.sadd('official_produce_fail', token)
                    for code, errmsg in res.errors:
                        logger.error("Pro Error: {}".format(errmsg))
                    if res.needs_retry():
                        logger.error('Pro need retry')
                        message = res.retry()
                    else:
                        break
                k += 1

        if not version or version == 'official_enterprise':
            k = 1
            while k <= 5:
                if redis.sismember('official_enterprise_fail', tokens):
                    break
                con = session_enter_pro.get_connection("push_production", cert_file="./enterprise_production.pem",
                                                       passphrase='mbmb')
                srv = APNs(con)
                try:
                    res = srv.send(message)
                except OpenSSL.SSL.WantReadError:
                    logger.error('want read error')
                except:
                    logger.error('Enter fail:', exc_info=True)
                else:
                    for token, reason in res.failed.items():
                        code, errmsg = reason
                        logger.error("Enter Device failed: {0}, reason: {1}".format(token, errmsg))
                        redis.sadd('official_enterprise_fail', token)
                    for code, errmsg in res.errors:
                        logger.error("Enter Error: {}".format(errmsg))
                    if res.needs_retry():
                        logger.error('Enter need retry')
                        message = res.retry()
                    else:
                        break
                k += 1

        if not version or version == 'micheng_produce':
            k = 1
            while k <= 5:
                if redis.sismember('micheng_produce_fail', tokens):
                    break
                con = session_micheng_pro.get_connection("push_production", cert_file="./MiCheng_production.pem",
                                                         passphrase='mbmb')
                srv = APNs(con)
                try:
                    res = srv.send(message)
                except OpenSSL.SSL.WantReadError:
                    logger.error('want read error')
                except:
                    logger.error('Michen fail:', exc_info=True)
                else:
                    for token, reason in res.failed.items():
                        code, errmsg = reason
                        logger.error("Michen Device failed: {0}, reason: {1}".format(token, errmsg))
                        redis.sadd('micheng_produce_fail', token)
                    for code, errmsg in res.errors:
                        logger.error("Michen Error: {}".format(errmsg))
                    if res.needs_retry():
                        logger.error('Michen need retry')
                        message = res.retry()
                    else:
                        break
                k += 1

        if not version or version == 'kele_develop':
            k = 1
            while k <= 5:
                if redis.sismember('kele_develop_fail', tokens):
                    break
                con = session_kele_dev.get_connection("push_sandbox", cert_file="./kele_development.pem",
                                                      passphrase='1234')
                srv = APNs(con)
                try:
                    res = srv.send(message)
                except OpenSSL.SSL.WantReadError:
                    logger.error('want read error')
                except:
                    logger.error('Kele fail:', exc_info=True)
                else:
                    for token, reason in res.failed.items():
                        code, errmsg = reason
                        logger.error("Kele Device failed: {0}, reason: {1}".format(token, errmsg))
                        redis.sadd('kele_develop_fail', token)
                    for code, errmsg in res.errors:
                        logger.error("Kele Error: {}".format(errmsg))
                    if res.needs_retry():
                        logger.error('Kele need retry')
                        message = res.retry()
                    else:
                        break
                k += 1

        if not version or version == 'kele_produce':
            k = 1
            while k <= 5:
                if redis.sismember('kele_produce_fail', tokens):
                    break
                con = session_kele_pro.get_connection("push_production", cert_file="./kele_production.pem",
                                                      passphrase='1234')
                srv = APNs(con)
                try:
                    res = srv.send(message)
                except OpenSSL.SSL.WantReadError:
                    logger.error('want read error')
                except:
                    logger.error('Kele fail:', exc_info=True)
                else:
                    for token, reason in res.failed.items():
                        code, errmsg = reason
                        logger.error("Kele Device failed: {0}, reason: {1}".format(token, errmsg))
                        redis.sadd('kele_produce_fail', token)
                    for code, errmsg in res.errors:
                        logger.error("Kele Error: {}".format(errmsg))
                    if res.needs_retry():
                        logger.error('Kele need retry')
                        message = res.retry()
                    else:
                        break
                k += 1
